﻿
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Security.Cryptography;
using System.Text.RegularExpressions;
using TMPro;
using UnityEngine;
using Object = UnityEngine.Object;
using Random = UnityEngine.Random;

public class Utils
{
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static float DistanceSq(Vector2 a, Vector2 b)
    {
        var c = a - b;
        return c.x * c.x + c.y * c.y;
    }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static Vector2 Clamp(Vector2 a, Vector2 min, Vector2 max)
    {
        a.x = Mathf.Clamp(a.x, min.x, max.x);
        a.y = Mathf.Clamp(a.y, min.y, max.y);
        return a;
    }
    
    
    private static readonly char[] arr = new char[10];
    private const char ZERO = '0';

    public static void SetNumber(TMP_Text tmpText, int n)
    {
        int i = 0;
        while (n > 0)
        {
            arr[i++] = (char)((n % 10) + ZERO);
            n /= 10;
        }
        
        // 反转
        if (i >= 2)
        {
            for (int j = 0; j < i / 2; j++)
            {
                (arr[j], arr[i - j - 1]) = (arr[i - j - 1], arr[j]);
            }
        }
        // 0GC
        tmpText.SetCharArray(arr, 0, i);
    }

    public static void SetTime(TMP_Text tmpText, float time)
    {
        int i = 0;
        int m = (int)time / 60;
        int s = (int)time % 60;
        if (m >= 10)
        {
            arr[i++] = (char)((m / 10) + ZERO);
        }
        else
        {
            arr[i++] = ZERO;
        }
        arr[i++] = (char)((m % 10) + ZERO);
        arr[i++] = ':';
        if (s >= 10)
        {
            arr[i++] = (char)((s / 10) + ZERO);
        }
        else
        {
            arr[i++] = ZERO;
        }
        arr[i++] = (char)((s % 10) + ZERO);
        tmpText.SetCharArray(arr, 0, i);
    }
    
    public static void DestroyAllChildren(Transform transform)
    {
        for (int i = transform.childCount - 1; i >= 0; i--)
        {
            Object.DestroyImmediate(transform.GetChild(i).gameObject);
        }
    }
    
    #region 时间
    private static readonly DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);

    public static int GetTimeInSeconds()
    {    
        var timeSpan = DateTime.UtcNow - epoch;
        return (int)timeSpan.TotalSeconds;
    }

    public static int GetTimeInSeconds(DateTime time)
    {    
        var timeSpan = time - epoch;
        return (int)timeSpan.TotalSeconds;
    }

    public static int GetTimeSpan(DateTime time)
    {
        var startTime = TimeZone.CurrentTimeZone.ToLocalTime(epoch);
        return (int)(time - startTime).TotalSeconds;
    }

    public static DateTime TimestampToDateTime(float timestamp)
    {
        var startTime = TimeZone.CurrentTimeZone.ToLocalTime(epoch);
        return startTime.AddSeconds(timestamp);
    }
    #endregion
    
    /// <summary>
    /// 校验邮箱是否合法
    /// </summary>
    /// <param name="email"></param>
    /// <returns></returns>
    public static bool IsEmailValid(string email)
    {
        const string patten = @"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$";
        return Regex.IsMatch(email, patten);
    }
    
    /// <summary>
    /// 生成二进制md5文件
    /// </summary>
    /// <param name="content"></param>
    /// <returns>长度位16的byte</returns>
    public static byte[] GetMD5(byte[] content)
    {
        return MD5.Create().ComputeHash(content);
    }
    
    public static bool IsSampMD5(byte[] b1, byte[] b2)
    {
        if (b1.Length != 16 || b2.Length != 16 || b1.Length != b2.Length)
        {
            return false;
        }
        for (int i = 0; i < 16; i++)
        {
            if (b1[i] != b2[i])
            {
                return false;
            }
        }
        return true;
    }

    public static int RandomWeight<T>(List<T> weights, Func<T, int> GetWeight)
    {
        int idx = -1;
        float rdValue = Random.Range(0f, 1f);
        float endWeight = 0;
        float totalWeight = 0;
        for (int i = 0; i < weights.Count; i++)
        {
            totalWeight += GetWeight(weights[i]) * rdValue;
            if (totalWeight >= endWeight)
            {
                idx++;
                endWeight += GetWeight(weights[i]);
            }
        }

        return idx;
    }

    public static void ClearTrails(GameObject go, Vector2 spawnPosition)
    {
        go.transform.localPosition = spawnPosition;
        // 重置拖尾
        var trailRenderers = go.GetComponentsInChildren<TrailRenderer>();
        foreach (var trail in trailRenderers)
        {
            trail.Clear();
        }
    }
}
